"""函数"""""
'''
基本格式
    def 函数名字(参数可选):
        代码体
        return 返回值
'''
# def basic_func (param:str):
#     if isinstance(param,str):
#         return param
#     raise TypeError('请输入字符串')

'''函数的类型'''


# 根据这个函数有无参数，及有无返回，可分为四类，有参无返回，有参有返回，无参无返回，无参有返回

# 有参无返回
def with_parm_no_return(param):
    a = param


# print(with_parm_no_return('1'))

# 有参有返回
def with_param_return(param: str):
    return param


# print(with_param_return('abc'))

# 无参无返回
def no_param_no_return():
    a = 1 + 2


# print(no_param_no_return())

# 无参有返回
def no_param_return():
    return 1 + 2


# print(no_param_return())

'''参数类型'''


# 形参：函数括号里定义的参数，称之为形式参数，简称形参
# 实参：函数调用阶段，括号内传入的参数，称之为实际参数，简称实参
# 参数类型：位置参数，默认值参数，关键字参数，不定长参数，强制位置参数
def param_type(a, b, c, d=None, *args, **kwargs):
    return f'a是{a}，b是{b}，c是{c}，d是{d}，元组包是{args}，字典包是{kwargs}'


# 位置参数:就是实参与形参的位置一一对应
# print(param_type(1, 2, 3))

# 默认值参数：如某个形参有默认值，且实参没有对其改变，那么该参数会取定义好的默认值
# print(param_type(1, 2, 3))

# 关键字参数:传入实参时，声明该实参对应的形参是谁
# print(param_type(c=4, a='a', b='A'))

# 不定长参数，在python中，处理不定长有两种方式，一个是使用可变参数，另一个是关键字参数
# 可变参数（*args），如果传入的参数很多，且没有找到对应的形参，那么*args会将这些实参，打包成一个元组
# 关键字参数（**kwagrs），如果传入的参数很多，且没有找到对应的形参，那么**kwagrs会将这些实参，打包成一个字典

# print(param_type(1, 2, 34, 5, 6, 6, 7, 8, 9, 0))
# print(param_type(1, 2, 3, 23, 4, 454554, 'adasd', name=1, age=24))

# 强制位置参数:python3.8之后新增了一个形参的语法“/”,它用来指明函数形参必须使用指定的位置参数，不能使用关键字参数
def greet(name, age, /, greeting='Hello'):
    return f'{greeting},{name}!You are {age} years old.'

# print(greet(name='dengze', 30)) # 错误的调用
# print(greet('dz', 28))

'''函数调用'''
# 函数名() ,有参填参，没参也得写小括号


'''递归函数'''
# 定义:递归函数说白了就是自己调用自己,递归函数需要一个明确的终止条件,如果不设置,会陷入死循环
# 递推:一层一层的递归调用下去,越往下,问题的规模会越小
# 回溯:递归遇到终止条件时,会往上一层一层的回溯,直到找到最初调用的值
# 注意事项:递归是采用栈结构实现的,所以说如果递推层数过多,会导致栈溢出

# def sum_nums_func(n): # 普通函数
#     """
#     :param n:n以内的计算
#     :return: n以内的和,偶数和,奇数和
#     """
#     num = 1
#     sum_nums, sum_even_num, sum_odd_num = 0, 0, 0  # 初始化和，偶数的和，奇数的和
#     while num <= n:
#         sum_nums += num
#         if num % 2 == 0:
#             sum_even_num += num
#         else:
#             sum_odd_num += num
#         num += 1
#     return f'1-{n}的和是：{sum_nums}，偶数和是：{sum_even_num}，奇数和是：{sum_odd_num}'
#
#
# def sum_nums_func1(n): # 递归函数
#     """
#     第一次递推,sum_nums_func1(5),返回的是 5 + sum_nums_func1(4)
#     第二次递推,sum_nums_func1(4),返回的是 4 + sum_nums_func1(3)
#     第三次递推,sum_nums_func1(3),返回的是 3 + sum_nums_func1(2)
#     第四次递推,sum_nums_func1(2),返回的是 2 + sum_nums_func1(1)
#     第五次递推,sum_nums_func1(1),遇到终止条件,返回1
#     第一次回溯(第四次递推):sum_nums_func1(2) = 2 + sum_nums_func1(1) = 2 + 1 = 3
#     第二次回溯(第三次的递推):sum_nums_func1(3) = 3 + sum_nums_func1(2) = 3 + 2 + 1 = 6
#     第三次回溯(第二次的递推):sum_nums_func1(4) = 4 + sum_nums_func1(3) = 4 + 3 + 2 + 1 = 10
#     第四次回溯(第一次的递推):sum_nums_func1(5) = 5 + sum_nums_func1(4) = 5 + 4 + 3 + 2 + 1 = 15
#     此时找到最初要计算的值,即sum_nums_func1(5),返回15,结束
#     """
#     if n == 1:
#         return 1
#     else:
#         return n + sum_nums_func1(n - 1)
# print(sum_nums_func1(5))
#
# """
# 快速排序:
#     它是一种高效的排序算法,它的思想采用分治法,将一个序列,分为较大和较小的两个子序列,然后递归的排序两个子序列,从而得到最终的有序序列
# """""
#
#
# def quicksort(ls):
#     if len(ls) <= 1:
#         return ls
#     pivot = ls[len(ls) // 2]  # 初始化基准值
#     left_ls = []
#     middle_ls = []
#     right_ls = []
#     for i in ls:
#         if i < pivot:
#             left_ls.append(i)
#         elif i > pivot:
#             right_ls.append(i)
#         elif i == pivot:
#             middle_ls.append(i)
#     return quicksort(left_ls) + middle_ls + quicksort(right_ls)
#
#
# a = [4, 32, 5, 12, 4, 214, 53, 8, 6, 3, 3, 123]
# print(quicksort(a))
#
#
# """
# 嵌套函数
#     定义:函数内部还有函数,就是嵌套函数
#     注意点:函数内部的函数,只能外层函数调用,外边的函数不可调用
# """""
#
#
# def outer_func():
#     def inner1():
#         return 'mike'
#     def inner2():
#         return 30
#     return f'my name is {inner1()} and {inner2()} years old'
#
# print(outer_func())


'''闭包函数'''
# 闭:指的是该函数是一个内部函数
# 包:该函数的名字在外部函数被引用
def outer1():
    print('外部函数正在运行')
    def inner():
        print('内部函数正在运行')
    return inner()
print(outer1())

"""
名称空间(namespace):创建的变量会在内存中开辟一个新的空间,该空间与变量之前存在绑定的关系,即这个空间就是名称空间
名称空间的分类:
    1.内置名称空间(built-in):在python中,内置的名称,像int,string,tuple,list,这些名称空间,就是内置名称空间,在解释器启动的时候
        生效,关闭的时候失效
    2.全局名称空间(global):在模块中或者在一个.py文件中,定义的变量,类,函数,这些对象对应的空间就是全局名称空间,在执行文件时生效,关闭失效
    3.局部名称空间(local):比如函数中定义的变量,这个变量所处的空间就是局部名称空间,当函数被调用的时候生效,不调用失效
名称空间查找顺序:l->g->b->报错
"""""

'''
作用域
    1.L(local):局部空间的作用域,局部作用域,比如函数内部定义的变量,可以在该函数的局部空间生效
    2.E(Enclosing):非全局作用域,比如函数A里包含了函数B,A里有一个变量,那么对于B来说,A的作用域就是非全局作用域
    3.G(Global):比如当前.py文件创建的变量,这个变量的作用域就是全局作用域
    4.B(Built-in):内建作用域,包含了一些python定义好的类,关键字,变量等
查找顺序:L->E->G->b
拓展:如果在全局作用域中,定义了一个变量,它的值是不可变类型的,我想在局部作用域修改它,怎么办?
    使用global关键字进行修改
    同理,我想在局部修改非全局的变量,怎么办?
    使用nonlocal关键字进行修改

'''

"""
类
    1.定义:用来描述具有相同的方法,属性的对象的集合,它定义了该集合中每个对象所共有的属性和方法,类的实例是对象
    2.表达式
        类名的命名规范：比如驼峰（帕斯卡命名）
        class 类名(继承的类,没有可不写):
            语句
    3.类里有什么?
        a.类属性,类中的全局变量
        b.实例属性,是类的实例化后的属性,可以使用装饰器,将实例方法变为实例属性
        c.类方法,类中定义的函数,需要使用装饰器,将实例方法转换为类方法
        d.实例方法,就是类中定义的函数        
"""""
'''init()'''

# 它的作用是将实例化的对象进行初始化
# 若类中定义了该方法,类的实例会自动调用这个方法
# 这个方法可以有参数，参数通过该方法传递给类的实例：self代表的是类的实例，cls代表的是类
# 类的方法和普通函数的区别，即类必有有一个额外的参数，即self
# 有无init()的区别
#     若类中定义了该方法，那么在执行的时候，会先调用该方法
#     若这个类没有父类及没有这个方法，那么该对象不会被初始化
#     若该类有父类，怎么优先调用父类的init()

'''拓展：私有化'''


# 如果你类中定义的方法，不想被看见，或者使用，怎么办？
# _代表不可见，但可用
# __代表即不可见,也不可用

class Intrduction:  # 没有写（），不写代表继承object类，它是python类中的祖宗
    human = '人类'  # 类属性，类中的所有成员都可以使用

    def __init__(self, name, age, sex):  # 构造一个初始化方法init()
        self.name = name  # 实例属性，将类实例化后，调用该类，需要传name的实参
        self.age = age
        self.sex = sex

    @property
    def human_sex(self):  # 将实例方法变为实例属性
        if self.sex == '男':
            return '他'
        elif self.sex == '女':
            return '她'
        else:
            return '它'

    def introduction(self):  # 定义一个实例方法
        return f'{self.name}今年{self.age}岁了，{self.human_sex}是一个{Intrduction.human}'

    @classmethod
    def introduction_class_func(cls):  # 创建一个类方法
        return f'这是一个{cls.human}'

    @staticmethod
    def _func(self):  # 定义一个静态方法,外部看不见，但能调用
        return 1 + 1

    @staticmethod
    def __func1(self):  # 定义一个静态方法,外部看不见，也不可以调用
        return 2 + 2
# 我想调用Intrduction类中的实例方法introduction怎么办？
# Intrduction() # 第一步：将类实例化
# Intrduction().introduction() # 第二步调用
# print(Intrduction('dz',28,'男').introduction()) # 实例方法的调用

# print(Intrduction.introduction_class_func()) 类方法的调用

# print(Intrduction.human) # 调用类属性
# print(Intrduction('dz', 28, '男').human_sex) #调用实例属性
# class Calculator:
#     def __init__(self):
#         pass
#
#     def add(self, a: int, b: int) -> int:
#         """加法运算"""
#         return a + b
#
#     def subtract(self, a: int, b: int) -> int:
#         """减法运算"""
#         return a - b
#
#     def multiply(self, a: int, b: int) -> int:
#         """乘法运算"""
#         return a * b
#
#     def divide(self, a: int, b: int) -> float:
#         """除法运算，需要检查除数是否为0"""
#         if b == 0:
#             raise ValueError("除数不能为0")
#         return a / b
#
#
# # 示例使用
# if __name__ == "__main__":
#     calc = Calculator()
#
#     a = int(input("请输入第一个整数："))
#     b = int(input("请输入第二个整数："))
#     operation = input("请输入运算符（+、-、*、/）：")
#
#     if operation == '+':
#         result = calc.add(a, b)
#     elif operation == '-':
#         result = calc.subtract(a, b)
#     elif operation == '*':
#         result = calc.multiply(a, b)
#     elif operation == '/':
#         result = calc.divide(a, b)
#     else:
#         print("不支持的运算符，请输入 +、-、* 或 /")
#         exit()
#
#     print(f"结果是：{result}")


# class Calculator:  # 仅支持整数,单次,加减乘除的计算器
#     def __init__(self):
#         try:
#             self.element1 = int(input("请输入第一个数字"))
#             self.element2 = int(input("请输入第二个数字"))
#         except Exception as error:
#             raise error
#         self.operation = input('您想进行什么运算？请输入+,-,*,/')
#
#     def __add(self):
#         return self.element1 + self.element2
#
#     def __subtract(self):
#         return self.element1 - self.element2
#
#     def __multiply(self):
#         return self.element1 * self.element2
#
#     def __divide(self):
#         if self.element2 == 0:
#             raise ValueError('Divisor cannot be zero')
#         return self.element1 / self.element2
#
#     def calculator(self):  # 使用计算器请调用该方法
#         if self.operation not in('+','-','*','/'):  # 当运算符输入无效时
#             raise ValueError('请输入合理的运算符 +,-,*,/ ')
#         elif self.operation == '+':
#             print(self.__add())
#         elif self.operation == '-':
#             print(self.__subtract())
#         elif self.operation == '*':
#             print(self.__multiply())
#         elif self.operation == '/':
#             print(self.__divide())
#
#
# if __name__ == '__main__':
#     Calculator().calculator()


"""类与继承"""



class aa():
    def __init__(self,name,age):
        self.name=name
        self.age=age


class dongwu(aa):
    # def __init__(self,name,age):
    #     self.name=name
    #     self.age=age
    def bb(self):
        pass

class prople(dongwu):
    # def __init__(self,name,age,job):
    #     self.name=name
    #     self.age=age
    #     self.job=job
    def __init__(self,name,age,job):
        super().__init__(name,age)
        self.job=job

    def zuofan(self):
        pass

    def speak(self):
        print("111")
class dog(dongwu):
    # def __init__(self,name,age):
    #     self.name=name
    #     self.age=age

    def QQ(self):
        pass

    def speak(self):
        print("111")

aa=prople('秦至诚',20,"运动员")
print(aa.job)


#组合，在不使用继承的写法写，实现类似与继承的效果，qin没钱请大家吃饭，所以强制掏deng的钱包请大家吃饭，但是qin和deng又没有继承关系\
# 组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象
